//孵化监控
const {EnumRole, EnumBehavior, EnumHarvestMode, EnumFlag, EnumCreepBody} = require("./Enum");
const {findRoleCreeps, findStore, findEnergyStore, findBuild, findRoomFlagList, findFlagList} = require("./Find");
const {build} = require("./Behavior");
module.exports.spawnMonitor = room => {
    if (!room.memory.spawnIndex || room.memory.spawnIndex > 999) {
        room.memory.spawnIndex = 1;
    }
    //如果存在队列
    let spawnList = room.memory.spawnList;
    if (!spawnList) {
        room.memory.spawnList = [];
        spawnList = [];
    }
    //排除掉已孵化士兵
    if (spawnList && spawnList.length > 0) {
        let roomCreepList = room.find(FIND_MY_CREEPS);
        let tempList = spawnList.slice();
        for (let i = 0; i < tempList.length; i++) {
            for (let j = 0; j < roomCreepList.length; j++) {
                if (tempList[i].name === roomCreepList[j].name.substring(0, roomCreepList[j].name.length - 1)) {
                    spawnList.splice(i, 1);
                    break;
                }
            }
        }
    }
    //Defense
    let invasionCreepList = room.find(FIND_HOSTILE_CREEPS);
    if (invasionCreepList.length > 0 && room.controller.level >= 2) {
        if(invasionCreepList[0].owner==="Invader"&&findBuild(room,STRUCTURE_TOWER).length>0){
            console.log("检测到npc入侵,存在炮塔,无需防御兵");
        }else{
            let spawningDefenseList = spawnList.filter(creep => creep.role === EnumRole.Defense);
            let defenseList = findRoleCreeps(EnumRole.Defense).filter(creep => creep.memory.createRoom===room.name);
            if (defenseList.length + spawningDefenseList < 2) {
                let creep = {
                    name: EnumRole.Defense + "_" + room.memory.spawnIndex + "_",
                    body: "Defense-lv",
                    role: EnumRole.Defense,
                    spawn: false,
                    memory: {
                        role: EnumRole.Defense,
                        behavior: EnumBehavior.Free,
                        createRoom: room.name,
                        workRoom: room.name,
                    },
                }
                room.memory.spawnIndex += 1;
                room.memory.spawnList.push(creep)
            }
        }
    }
    let sourceList = room.find(FIND_SOURCES);
    //Harvest
    //Number is resource size
    let spawningHarvestList = spawnList.filter(creep => creep.role === EnumRole.Harvest);
    let harvestList = findRoleCreeps(EnumRole.Harvest, room).filter(creep => creep.ticksToLive > 150);
    if (harvestList.length + spawningHarvestList.length < sourceList.length) {
        let creep = {
            name: EnumRole.Harvest + "_" + room.memory.spawnIndex + "_",
            body: "Harvest-lv",
            role: EnumRole.Harvest,
            spawn: false,
            memory: {
                role: EnumRole.Harvest,
                behavior: EnumBehavior.Free,
                createRoom: room.name,
                workRoom: room.name,
            },
        }
        room.memory.spawnIndex += 1;
        room.memory.spawnList.push(creep)
    }
    //Butler
    //Number is resource size +1
    let spawningButlerList = spawnList.filter(creep => creep.role === EnumRole.Butler);
    let butlerList = findRoleCreeps(EnumRole.Butler, room).filter(creep => creep.ticksToLive > 100);
    if (butlerList.length > 0) {//存在Butler修改为OnlyHarvest
        room.memory.mode = EnumHarvestMode.OnlyHarvest;
    }
    let spawnButlerSize = 3;
    if (room.controller.level > 3) {
        spawnButlerSize = 2;
    }
    if (room.controller.level > 6) {
        spawnButlerSize = 1
    }
    if (butlerList.length + spawningButlerList.length < spawnButlerSize) {
        let creep = {
            name: EnumRole.Butler + "_" + room.memory.spawnIndex + "_",
            body: "Butler-lv",
            role: EnumRole.Butler,
            memory: {
                role: EnumRole.Butler,
                behavior: EnumBehavior.Free,
                createRoom: room.name,
                workRoom: room.name,
            },
            spawn: false
        }
        room.memory.spawnIndex += 1;
        room.memory.spawnList.push(creep)
    }
    //Engineer
    //Number start = 2
    let spawnEngineSize = 2;
    let spawningEngineList = spawnList.filter(creep => creep.role === EnumRole.Engineer);
    let engineList = findRoleCreeps(EnumRole.Engineer, room).filter(creep => creep.ticksToLive > 100);
    //if exist more prepareBuildList
    let prepareBuildList = room.find(FIND_MY_CONSTRUCTION_SITES);
    let prepareResource = 0;
    let usedStoreList = findEnergyStore(room).filter(build => build.usedStore() > 0);
    if (prepareBuildList.length > 0) {
        for (let prepareBuild of prepareBuildList) {
            prepareResource += (prepareBuild.progressTotal - prepareBuild.progress)
        }
        if (prepareResource > 200000 && usedStoreList.length>=3) {
            spawnEngineSize += 3;
        } else if (prepareResource > 50000 && usedStoreList.length>=2) {
            spawnEngineSize += 2
        } else if (prepareResource > 30000 && usedStoreList.length>=2) {
            spawnEngineSize += 1;
        }
    }
    if(room.storage){
        if(room.storage.usedStore()>500000){
            spawnEngineSize += 3;
        }
        if(room.storage.usedStore()>200000){
            spawnEngineSize += 2;
        }
        if(room.storage.usedStore()>80000){
            spawnEngineSize += 1;
        }
    }

    let dropResourceList = room.find(FIND_DROPPED_RESOURCES);
    let dropAmount = 0;
    for (let drop of dropResourceList) {
        dropAmount += drop.amount;
    }
    if(room.controller.level<=3){
        spawnEngineSize += dropAmount / 2000;
    }
    let freeStoreList=findEnergyStore(room).filter(build=>build.freeStore()>0);
    if (spawnEngineSize < 6 && Game.time % 300 === 0 && spawnList.length === 0 && freeStoreList.length === 0) {
        spawnEngineSize = engineList.length + spawningEngineList.length + 1;
    }
    if (findBuild(room, STRUCTURE_TOWER).length === 0 || room.controller.level <= 3) {
        spawnEngineSize += 1;
    }
    if (spawnEngineSize > 8) {//can not super 8 engine
        spawnEngineSize = 8;
    }
    if (engineList.length + spawningEngineList.length < spawnEngineSize) {
        let creep = {
            name: EnumRole.Engineer + "_" + room.memory.spawnIndex + "_",
            body: "Engineer-lv",
            role: EnumRole.Engineer,
            spawn: false,
            memory: {
                role: EnumRole.Engineer,
                behavior: EnumBehavior.Free,
                createRoom: room.name,
                workRoom: room.name,
            },
        }
        room.memory.spawnIndex += 1;
        room.memory.spawnList.push(creep)
    }
    //upRostTeam
    let upRootList = findRoomFlagList(room, EnumFlag.UpRoot);
    let upRootToList = findFlagList(EnumFlag.UpRootTo);
    let upRootSpawn = true;
    let canOccupySpawn = true;
    if (upRootToList.length > 0) {
        if (upRootToList[0].room.controller.level >= 4) {
            upRootToList[0].remove();
            upRootSpawn = false;
        }
        if (upRootToList[0].room.controller.my) {
            canOccupySpawn = false;
        }
    }
    if (upRootSpawn && upRootList.length > 0) {
        //priority 1, 2 outHarvest not bind resource
        //priority 2, 2 outEngineer
        //priority 3, 1 occupy
        let spawningOutHarvestList = spawnList.filter(creep => creep.role === EnumRole.OutHarvest);
        let outHarvestList = findRoleCreeps(EnumRole.OutHarvest).filter(creep => creep.ticksToLive > 200);
        if (outHarvestList.length + spawningOutHarvestList.length < 2) {//start spawn
            let creep = {
                name: EnumRole.OutHarvest + "_" + room.memory.spawnIndex + "_",
                body: "OutHarvest-lv",
                role: EnumRole.OutHarvest,
                spawn: false,
                memory: {
                    role: EnumRole.OutHarvest,
                    behavior: EnumBehavior.Free,
                    createRoom: room.name,
                    workRoom: null,
                },
            }
            room.memory.spawnIndex += 1;
            room.memory.spawnList.push(creep)
        }
        let spawningOutEngineerList = spawnList.filter(creep => creep.role === EnumRole.OutEngineer);
        let outEngineerList = findRoleCreeps(EnumRole.OutEngineer).filter(creep => creep.ticksToLive > 150);
        if (outEngineerList.length + spawningOutEngineerList.length < 4) {
            let creep = {
                name: EnumRole.OutEngineer + "_" + room.memory.spawnIndex + "_",
                body: "OutEngineer-lv",
                role: EnumRole.OutEngineer,
                spawn: false,
                memory: {
                    role: EnumRole.OutEngineer,
                    behavior: EnumBehavior.Free,
                    createRoom: room.name,
                    workRoom: null,
                },
            }
            room.memory.spawnIndex += 1;
            room.memory.spawnList.push(creep)
        }
        let spawningOutOccupyList = spawnList.filter(creep => creep.role === EnumRole.Occupy);
        let outOccupyList = findRoleCreeps(EnumRole.Occupy);
        if (canOccupySpawn && outOccupyList.length + spawningOutOccupyList.length <= 0) {
            let creep = {
                name: EnumRole.Occupy + "_" + room.memory.spawnIndex + "_",
                body: "Occupy-lv",
                role: EnumRole.Occupy,
                spawn: false,
                memory: {
                    role: EnumRole.Occupy,
                    behavior: EnumBehavior.Free,
                    createRoom: room.name,
                    workRoom: null,
                },
            }
            room.memory.spawnIndex += 1;
            room.memory.spawnList.push(creep)
        }
    }
    //remove outRemoveTeam
    let removeFlagList = findRoomFlagList(room, EnumFlag.Remove);
    if (removeFlagList.length > 0) {
        let outWorkList = findRoleCreeps(EnumRole.OutWorker).filter(creep => creep.ticksToLive > 200);
        let spawningOutWorkList = spawnList.filter(creep => creep.role === EnumRole.OutWorker);
        if (outWorkList.length + spawningOutWorkList.length < 3) {//start spawn
            let creep = {
                name: EnumRole.OutWorker + "_" + room.memory.spawnIndex + "_",
                body: "OutWorker-lv",
                role: EnumRole.OutWorker,
                spawn: false,
                memory: {
                    role: EnumRole.OutWorker,
                    behavior: EnumBehavior.Free,
                    createRoom: room.name,
                    workRoom: null,
                },
            }
            room.memory.spawnIndex += 1;
            room.memory.spawnList.push(creep)
        }
    }
    //outTrans
    let outTransFlagList = findRoomFlagList(room, EnumFlag.Trans);
    if (outTransFlagList.length > 0) {
        let outTransList = findRoleCreeps(EnumRole.OutTrans).filter(creep => creep.ticksToLive > 100);
        let spawningOutTransList = spawnList.filter(creep => creep.role === EnumRole.OutTrans);
        if (outTransList.length + spawningOutTransList.length < 5) {//start spawn
            let creep = {
                name: EnumRole.OutTrans + "_" + room.memory.spawnIndex + "_",
                body: "OutTrans-lv",
                role: EnumRole.OutTrans,
                spawn: false,
                memory: {
                    role: EnumRole.OutTrans,
                    behavior: EnumBehavior.Free,
                    createRoom: room.name,
                    workRoom: null,
                },
            }
            room.memory.spawnIndex += 1;
            room.memory.spawnList.push(creep)
        }
    }


    //attack
    let attackFlagList = findRoomFlagList(room, EnumFlag.Attack);
    if (attackFlagList.length > 0 && room.controller.level >= 4) {
        let attackList = findRoleCreeps(EnumRole.Attack).filter(creep => creep.ticksToLive > 50);
        let spawningAttackList = spawnList.filter(creep => creep.role === EnumRole.Attack);
        if (attackList.length + spawningAttackList.length < 3) {//start spawn
            let creep = {
                name: EnumRole.Attack + "_" + room.memory.spawnIndex + "_",
                body: "Attack-lv",
                role: EnumRole.Attack,
                spawn: false,
                memory: {
                    role: EnumRole.Attack,
                    behavior: EnumBehavior.Free,
                    createRoom: room.name,
                    workRoom: null,
                },
            }
            room.memory.spawnIndex += 1;
            room.memory.spawnList.push(creep)
        }
    }
}

module.exports.spawning = (room, emptyStoreList) => {
    /**
     * before:
     * 1.spawnList is not empty
     * 2.spawner is ready
     *
     * tip.energy is not full,less creep level
     */
    let spawnList = room.memory.spawnList;

    if (spawnList && spawnList.length > 0) {//exist spawnList start
        /**
         * spawn priority
         * 1.harvest
         * 2.Butler
         * 3.Engineer
         * 6.Other
         */
        let defenseSpawnList = spawnList.filter(spawn => !spawn.spawn && spawn.role === EnumRole.Defense);
        let harvestSpawnList = spawnList.filter(spawn => !spawn.spawn && spawn.role === EnumRole.Harvest);
        let butlerSpawnList = spawnList.filter(spawn => !spawn.spawn && spawn.role === EnumRole.Butler);
        let engineSpawnList = spawnList.filter(spawn => !spawn.spawn && spawn.role === EnumRole.Engineer);
        let outSpawnList = spawnList.filter(spawn => !spawn.spawn && (spawn.role === EnumRole.OutEngineer||spawn.role === EnumRole.OutHarvest||spawn.role === EnumRole.OutWorker||spawn.role === EnumRole.Attack || spawn.role === EnumRole.OutTrans));
        let occupySpawnList = spawnList.filter(spawn => !spawn.spawn && spawn.role === EnumRole.Occupy);
        let level = room.controller.level;
        let upRoomToList=findRoomFlagList(room,EnumFlag.UpRootTo);
        //寻找空母巢
        let freeSpawnList = findBuild(room, STRUCTURE_SPAWN).filter(spawn => spawn.spawning === null)
        if (freeSpawnList.length <= 0) {//暂无Free
            return;
        }
        let hostileCreepList = room.find(FIND_HOSTILE_CREEPS);
        if(hostileCreepList.length===0){
            room.memory.spawnList=spawnList.filter(spawn => !spawn.spawn && spawn.role !== EnumRole.Defense);
        }
        if (defenseSpawnList.length > 0 && hostileCreepList.length>0) {
            deepSpawn(defenseSpawnList, freeSpawnList, level);
            return;
        }
        if (harvestSpawnList.length > 0  && upRoomToList.length===0) {
            deepSpawn(harvestSpawnList, freeSpawnList, level);
            return;
        }
        if (butlerSpawnList.length > 0) {
            deepSpawn(butlerSpawnList, freeSpawnList, level);
            return;
        }
        if (occupySpawnList.length > 0) {
            deepSpawn(occupySpawnList, freeSpawnList, level);
            return;
        }
        if (engineSpawnList.length > 0 && upRoomToList.length===0) {
            deepSpawn(engineSpawnList, freeSpawnList, level);
            return;
        }
        if (outSpawnList.length > 0) {
            deepSpawn(outSpawnList, freeSpawnList, Math.max(level - 1, 1));
            return;
        }
    }
}


const deepSpawn = (spawnList, freeSpawnList, level) => {
    let creep = spawnList[0];
    let spawn = freeSpawnList[0];
    let fullStoreList = findEnergyStore(spawn.room).filter(build => build.usedStore() > 0);
    let butlerList = findRoleCreeps(EnumRole.Butler, spawn.room);
    while (level >= 1) {//if level>1,meanwhile energy is not full,can all less level
        let spawnState = spawn.spawnCreep(EnumCreepBody[creep.body + level], creep.name + level, {memory: creep.memory})
        if (spawnState === OK) {
            creep.spawn = true;
            console.log(spawn.name + ":Spawning Success:" + creep.name + level);
            break;
        } else if (spawnState === ERR_NOT_ENOUGH_ENERGY && (fullStoreList.length <= 0 || butlerList.length <= 0 || spawn.room.controller.level - 1 < level)) {
            level--;
        } else {
            break;
        }
    }
}